use std::sync::Arc;

use crate::classfile;

use super::{ConstantPool, class::Class, field::Field};

// 字段符号引用
#[derive(Clone)]
pub struct FieldRef{
    cp: Arc<ConstantPool>,
    class_name: String, // 类的完全限定名
    class: Option<Arc<Class>>, // 缓存解析后的类结构体
    // cp_symref ↑
    name: String,
    descriptor: String,
    // cp_memberref ↑
    field: Option<Arc<Field>>, // 缓存解析的field
}

// cp_symref
impl FieldRef {
    // 字段符号引用解析
    pub fn resolved_class(&mut self) -> Arc<Class> {
        if self.class.is_none() {
            self.resolve_class_ref();
        }
        self.class.as_ref().unwrap().clone()
    }

    // 解析class引用
    fn resolve_class_ref(&mut self) {
        let d = self.cp.get_class();
        let loader = d.get_class_loader().unwrap();
        // TODO class_name 用的clone，后续调整标记
        let c = loader.lock().unwrap().load_class(self.class_name.clone());
        if !c.is_accessible_to(d.as_ref()) {
            panic!("java.lang.IllegalAccessError");
        }
        self.class = Some(c);
    }
}
#[allow(warnings)]
// cp_memberref
impl FieldRef {
    // 从class文件内存储的字段或方法常量中提取数据
    pub fn copy_member_ref_info(&mut self, ref_info: &classfile::ConstantFieldrefInfo) {
        self.class_name = ref_info.class_name();
        let (name, deciroptor) = ref_info.name_and_descriptor();
        self.name = name;
        self.descriptor = deciroptor;
    }

    pub fn get_name(&self) -> &str {
        &self.name
    }

    pub fn get_descriptor(&self) -> &str {
        &self.descriptor
    }
}

impl FieldRef {
    pub fn new_field_ref(cp: Arc<ConstantPool>, ref_info: &classfile::ConstantFieldrefInfo) -> FieldRef {
        let mut field_ref = FieldRef { 
            cp, 
            class_name: String::default(), 
            class: None, 
            name: String::default(), 
            descriptor: String::default(), 
            field: None 
        };
        field_ref.copy_member_ref_info(ref_info);
        field_ref
    }

    // 字段符号引用解析
    pub fn resolved_field(&mut self) -> Arc<Field> {
        if self.field.is_none() {
            self.resolve_field_ref()
        }
        self.field.clone().unwrap()
    }

    // 解析字段引用
    fn resolve_field_ref(&mut self) {
        let c = self.resolved_class();
        let d = self.cp.get_class();
        match Self::lookup_field(c, &self.name, &self.descriptor) {
            Some(field) if !field.is_accessible_to(d) => panic!("java.lang.IllegalAccessError"), // 无权访问
            Some(field) => self.field = Some(field), // 设置field
            None => panic!("java.lang.NoSuchFieldError")
        }
    }

    // 查找字段
    fn lookup_field(c: Arc<Class>, name: &str, descriptor: &str) -> Option<Arc<Field>> {
        // let match_name_and_type = |field: &Rc<RefCell<Field>>| field.get_name() == name && field.get_descriptor() == descriptor;
        // 从class字段查找
        for field in c.get_fields(false) {
            if field.get_name() == name && field.get_descriptor() == descriptor {
                return Some(field);
            }
        }
        // if let Some(field) = c.get_field_by_fn(match_name_and_type) {
        //     return Some(field);
        // }
        // 从接口中查找
        for iface in c.get_interfaces() {
            if let Some(field) = Self::lookup_field(iface.clone(), name, descriptor) {
                return Some(field);
            }
        }
        // 从父类查找
        if let Some(super_class) = c.get_super_class() {
            return Self::lookup_field(super_class, name, descriptor);
        }
        None
    }
}
